package com.hbzhit.modules.wx.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hbzhit.common.utils.R;
import com.hbzhit.modules.enums.WeiXinEnum;
import com.hbzhit.modules.sys.entity.SysOrgEntity;
import com.hbzhit.modules.sys.entity.SysUserEntity;
import com.hbzhit.modules.sys.service.SysOrgService;
import com.hbzhit.modules.sys.service.SysUserService;
import com.hbzhit.modules.wx.service.WxUserService;
import lombok.SneakyThrows;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class WxUserServiceImpl implements WxUserService {

    @Resource
    private SysOrgService orgService;
    @Resource
    private SysUserService userService;
    @Resource
    RedisTemplate<String, Object> dbRedis;

    @Override
    public String getAccessToken() throws Exception {
        Object cache = dbRedis.opsForValue().get("WECOM:ACCESS_TOKEN");

        if (ObjectUtil.isNotEmpty(cache)) {
            return (String) cache;
        }

        JSONObject result = new JSONObject(HttpUtil.get(String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", WeiXinEnum.CORP_ID.getValue(), WeiXinEnum.CORP_SECRET.getValue())));
        if (0 == (int) result.get("errcode")) {
            String accessToken = (String) result.get("access_token");
            dbRedis.opsForValue().set("WECOM:ACCESS_TOKEN", accessToken, 6500, TimeUnit.SECONDS);
            return accessToken;
        }

        throw new Exception((String) result.get("errmsg"));
    }

    @SneakyThrows
    @Override
    public List<SysOrgEntity> getDepartmentList(String accessToken) {
        JSONObject result = post("https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%s", JSONUtil.createObj(), accessToken);

        if (result.getInt("errcode") == 0) {
            return result.getJSONArray("department").stream().map(x -> {
                JSONObject item = (JSONObject) x;
                SysOrgEntity org = new SysOrgEntity();
                org.setOrgId(item.getLong("id"));
                org.setOrgName(item.getStr("name"));
                org.setPid(item.getLong("parentid"));
                String userid = new JSONArray(item.getStr("department_leader")).getStr(0);
                if (StrUtil.isNotEmpty(userid)) org.setMainUser(getConversionOpenId(accessToken, userid));
                return org;
            }).collect(Collectors.toList());

        }
        throw new Exception(result.getStr("errmsg"));
    }

    @SneakyThrows
    @Override
    public List<SysUserEntity> getUserList(String accessToken, Long departmentId, Integer fetchChild) {
        JSONObject result = post("https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=%s&department_id=%s&fetch_child=%s", JSONUtil.createObj(), accessToken, departmentId, fetchChild);

        if (result.getInt("errcode") == 0) {
            return result.getJSONArray("userlist").stream().map(x -> {
                JSONObject item = (JSONObject) x;
                String userid = item.getStr("userid");
                SysUserEntity sysUser = new SysUserEntity();
                if (StrUtil.isNotEmpty(userid) && ObjectUtil.notEqual(item.getStr("name"), "公用账号")) {
                    //随机八位加盐
                    sysUser.setSalt(RandomUtil.randomStringUpper(8));
                    sysUser.setUsername(item.getStr("userid"));
                    //sha256加密
                    sysUser.setPassword(new Sha256Hash("123456", sysUser.getSalt()).toHex());
                    sysUser.setRealName(item.getStr("name"));
                    sysUser.setMobile(item.getStr("mobile"));
                    sysUser.setDeptId(departmentId);
                    sysUser.setJob(item.getStr("position"));
                    sysUser.setSex(item.getInt("gender"));
                    sysUser.setEmail(item.getStr("email"));
                    sysUser.setIsMember(1);
                    sysUser.setOpenid(getConversionOpenId(accessToken, userid));
                }
                return sysUser;
            }).collect(Collectors.toList());
        }

        throw new Exception(result.getStr("errmsg"));
    }

    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean peopleSync() {
        String accessToken = getAccessToken();
        List<SysUserEntity> newUserList = new ArrayList<>();
        List<SysOrgEntity> newOrgList = new ArrayList<>();
        getDepartmentList(accessToken).forEach(org -> {
            //查询数据库是否已存在该部门记录，存在则修改，不存在新增
            SysOrgEntity oldOrg = orgService.getOne(new LambdaQueryWrapper<SysOrgEntity>().eq(SysOrgEntity::getOrgId, org.getOrgId()));
            if (ObjectUtil.isNotEmpty(oldOrg))
                orgService.update(org, new LambdaQueryWrapper<SysOrgEntity>().eq(SysOrgEntity::getOrgId, org.getOrgId()));
            else newOrgList.add(org);

            //微信部门人员不为空则遍历人员，判断数据库是否已有该人员，有则修改，没有则新增
            List<SysUserEntity> userList = new ArrayList<>();
            if (org.getOrgId() != 1) userList = getUserList(accessToken, org.getOrgId(), 0);
            if (CollectionUtil.isNotEmpty(userList)) {
                userList.forEach(user -> {
                    //根据微信openid去查询数据库是否有该人员存在
                    SysUserEntity oldUser = userService.getOne(new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getOpenid, user.getOpenid()));
                    if (ObjectUtil.isNotEmpty(oldUser))
                        userService.update(user, new LambdaQueryWrapper<SysUserEntity>().eq(SysUserEntity::getOpenid, user.getOpenid()));
                    else if (StrUtil.isNotEmpty(user.getOpenid())) newUserList.add(user);
                });
            }
        });
        if (CollectionUtil.isNotEmpty(newOrgList)) {
            return orgService.saveBatch(newOrgList);
        }
        if (CollectionUtil.isNotEmpty(newUserList)) {
            return userService.saveBatch(newUserList);
        }
        return true;
    }

    @SneakyThrows
    @Override
    public String getOpenidByCode(String code) {

        //小程序获取openid
        /*JSONObject result = new JSONObject(HttpUtil.get(String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", WeiXinEnum.APPID.getValue(), WeiXinEnum.SECRET.getValue(), code)));
        return result.getStr("openid");*/

        JSONObject result = new JSONObject(HttpUtil.get(String.format("https://qyapi.weixin.qq.com/cgi-bin/miniprogram/jscode2session?access_token=%s&js_code=%s&grant_type=authorization_code", getAccessToken(), code)));
        if (result.getInt("errcode") == 0) {
            return getConversionOpenId(getAccessToken(), result.getStr("userid"));
        }
        return null;
    }

    /**
     * 获取企业微信用户详细信息
     *
     * @param accessToken
     * @param userId
     * @return
     */
    @SneakyThrows
    public JSONObject getUserInfo(String accessToken, String userId) {
        JSONObject result = post("https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s", JSONUtil.createObj(), accessToken, userId);
        if (result.getInt("errcode") == 0) {
            return result;
        }
        throw new Exception(result.getStr("errmsg"));
    }

    /**
     * 用户userId转换openid
     *
     * @param accessToken
     * @param userId      企业微信用户id
     * @return
     */
    @SneakyThrows
    public String getConversionOpenId(String accessToken, String userId) {
        JSONObject params = JSONUtil.createObj();
        params.set("userid", userId);
        JSONObject result = post("https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token=%s", params, accessToken);
        if (result.getInt("errcode") == 0) {
            return result.getStr("openid");
        }
        throw new Exception(result.getStr("errmsg"));
    }

    public JSONObject post(String url, JSONObject params, Object... args) {
        return new JSONObject(HttpUtil.post(String.format(url, args), params.toString()));
    }
}
